package com.pshare.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import org.apache.log4j.Logger;

/**
 * 随机验证码生成工具
 */
public class RandomCodeUtils {

	private static final Logger logger = Logger.getLogger(RandomCodeUtils.class);

	/** 图片流 */
	private byte[] image;

	/** 验证码 */
	private String code;

	public static final int WIDTH = 92;

	public static final int HEIGHT = 36;

	private RandomCodeUtils() {
		init();
	}

	public static RandomCodeUtils instance() {
		return new RandomCodeUtils();
	}

	public byte[] getImage() {
		return image;
	}

	public String getCode() {
		return code;
	}

	private void init() {
		// 在内存中创建图象
		int width = WIDTH, height = HEIGHT;
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

		// 获取图形上下文
		Graphics g = image.getGraphics();
		// 生成随机类
		Random random = new Random();
		// 设定背景色
		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);
		// 设定字体
		g.setFont(new Font("Time News Roman", Font.ROMAN_BASELINE, 24));

		// 随机产生300条干扰线，使图象中的认证码不易被其它程序探测到
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 300; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		// 取随机产生的认证码(N位数字)
		String sRand = "";
		for (int i = 0; i < 4; i++) {
			// String rand=String.valueOf(random.nextInt(10));
			String rand = getRandomChar();
			sRand = sRand.concat(rand);
			// 将认证码显示到图象中
			g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
			// 调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成
			g.drawString(rand, 13 * i + 24, 24);
		}
		this.code = sRand;/* 赋值验证码 */
		// 图象生效
		g.dispose();
		byte[] b = null;
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
			ImageIO.write(image, "JPEG", imageOut);
			imageOut.close();
			b = output.toByteArray();
		} catch (Exception e) {
			logger.error("验证码图片产生出现错误：" + e.toString());
		}
		this.image = b;/* 赋值图像 */
	}

	/*
	 * 给定范围获得随机颜色
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}

	/***
	 * 
	 * 产生随机数字或字符
	 */
	public static String getRandomChar() {
		int index = (int) Math.round(Math.random() * 2);
		String randChar = "";
		switch (index) {
		case 0:// 大写字符
			randChar = String.valueOf((char) Math.round(Math.random() * 25 + 65));
			break;
		case 1:// 小写字符
			randChar = String.valueOf((char) Math.round(Math.random() * 25 + 97));
			break;
		default:// 数字
			randChar = String.valueOf(Math.round(Math.random() * 9));
			break;
		}
		return randChar;
	}

	/**
	 * 产生规定位数的小写字母或数字
	 * 
	 * @param len
	 * @return String
	 */
	public static String getRandomNumOrLowerCaseStr(int len) {
		return getRandomNumOrLetterStr(len, 1);
	}

	/**
	 * 产生规定位数的大写字母或数字
	 * 
	 * @param len
	 * @return String
	 */
	public static String getRandomNumOrUpperCaseStr(int len) {
		return getRandomNumOrLetterStr(len, 2);
	}

	/**
	 * 产生规定位数的字母或数字
	 * 
	 * @param len
	 * @return String
	 */
	public static String getRandomNumOrCaseStr(int len) {
		return getRandomNumOrLetterStr(len, null);
	}

	/**
	 * 产生规定位数的字母或数字
	 * 
	 * @param len
	 * @param case 是否大小写 1: 小写，2：大写，null:不限
	 * @return String
	 */
	public static String getRandomNumOrLetterStr(int len, Integer loweroruppcase) {
		String sRand = "";
		for (int i = 0; i < len; i++) {
			String rand = getRandomChar();
			sRand = sRand.concat(rand);
		}
		if (loweroruppcase != null) {
			if (1 == loweroruppcase) {
				sRand = sRand.toLowerCase();
			} else if (2 == loweroruppcase) {
				sRand = sRand.toUpperCase();
			}
		}

		return sRand;
	}

	public static String getRandomNum(int len) {
		String reqCode = "";
		for (int i = 0; i < len; i++) {
			reqCode += String.valueOf(Math.round(Math.random() * 9));
		}

		return reqCode;
	}

	public static String getRandomVerifyCode() {
		Integer value = (int) ((Math.random() * 9 + 1) * 100000);
		return "" + value;
	}

	public static void main(String[] args) {
		System.out.println(RandomCodeUtils.getRandomVerifyCode());
	}

}
